import { test } from '@jest/globals';
import { iconv } from '@ohos/hvigor';
import assert from 'assert';

const testString = 'Hello123!';
const testStringLatin1 = 'Hello123!£Å÷×çþÿ¿®';
const sampleStr = '<?xml version="1.0" encoding="UTF-8"?>\n<俄语>данные</俄语>';
const strBOM = '\ufeff';
const utf8BOM = Buffer.from([0xEF, 0xBB, 0xBF]);

describe('UTF-8 tests', function () {
  test.concurrent('can encode/decode internal encodings', async () => {
    const buf = iconv.encode('💩', 'utf8');
    const str = iconv.decode(buf, 'utf8');
    assert.equal(str, '💩');
  });

  test.concurrent('Return values are of correct types', async () => {
    assert.ok(Buffer.isBuffer(iconv.encode(testString, 'utf8')));

    const s = iconv.decode(Buffer.from(testString), 'utf8');
    assert.strictEqual(Object.prototype.toString.call(s), '[object String]');
  });

  test.concurrent('Internal encodings all correctly encoded/decoded', async () => {
    assert.strictEqual(iconv.encode(testStringLatin1, 'utf8').toString('utf8'), testStringLatin1);
    assert.strictEqual(iconv.decode(Buffer.from(testStringLatin1, 'utf8'), 'utf8'), testStringLatin1);
  });

  test.concurrent('handles Object & Array prototypes monkey patching', async () => {
    // eslint-disable-next-line no-extend-native
    Object.defineProperty(Object.prototype, 'permits', {
      value: () => {
        // nothing
      },
      writable: true,
      enumerable: true,
      configurable: true,
    });
    // eslint-disable-next-line no-extend-native
    Object.defineProperty(Array.prototype, 'sample2', {
      value: () => {
        // nothing
      },
      writable: true,
      enumerable: true,
      configurable: true,
    });

    assert.strictEqual(iconv.decode(Buffer.from('abc'), 'utf8'), 'abc');
    assert.strictEqual(iconv.encode('abc', 'utf8').toString(), 'abc');
  });

  test.concurrent('strips UTF-8 BOM', async () => {
    const body = Buffer.concat([utf8BOM, Buffer.from(sampleStr)]);
    assert.equal(iconv.decode(body, 'utf8'), sampleStr);
  });

  test.concurrent('doesn\'t strip BOMs when stripBOM=false', async () => {
    const body = Buffer.concat([utf8BOM, Buffer.from(sampleStr)]);
    assert.equal(iconv.decode(body, 'utf8', { stripBOM: false }), strBOM + sampleStr);
  });

  test.concurrent('adds UTF-8 BOM when addBOM=true', async () => {
    const body = Buffer.concat([utf8BOM, Buffer.from(sampleStr)]).toString('hex');
    assert.equal(iconv.encode(sampleStr, 'utf8', { addBOM: true }).toString('hex'), body);
  });
});
